#!/usr/bin/python
# -*- coding: utf-8 -*-

from django.contrib.auth.models import User
from django.conf import settings
from django.utils.safestring import mark_safe
import hmac
import MySQLdb
import time

def get_passwd_from_wpdb(username):
    '''
    # 根据指定的用户名，在wordpress数据库内查询该用户密码
    @param username:
    @type username:
    '''
    '''
    make a mysql connector , use raw sql, get password by username
    @param username:
    @type username:
    '''
    wpdb = MySQLdb.connect(host=settings.WP_DATABASE_HOST, \
                         port=settings.WP_DATABASE_PORT, \
                         user=settings.WP_DATABASE_USER, \
                         passwd=settings.WP_DATABASE_PASSWORD, \
                         db=settings.WP_DATABASE_NAME)
    wpdb_cursor = wpdb.cursor()
    wpdb_cursor.execute("""SELECT `user_pass` FROM `%susers` WHERE `user_login` = '%s'""" % (settings.WP_DB_PREFIX, mark_safe(username)))
    user_passwd = wpdb_cursor.fetchone()

    return user_passwd[0]

def wp_salt(scheme='auth'):
    '''
    # 根据指定的 scheme 返回相应的salt字串
    @param scheme:
    @type scheme:
    '''

    if scheme == 'auth':
        secret_key = settings.WP_AUTH_KEY
        salt = settings.WP_AUTH_SALT
    elif scheme == 'logged_in':
        secret_key = settings.WP_LOGGED_IN_KEY
        salt = settings.WP_LOGGED_IN_SALT
    elif scheme == 'secure_auth':
        secret_key = settings.WP_SECURE_AUTH_KEY
        salt = settings.WP_SECURE_AUTH_SALT
    elif scheme == 'nonce':
        secret_key = settings.WP_NONCE_KEY
        salt = settings.WP_NONCE_SALT
    else:
        secret_key = ''
        salt = ''

    return '%s%s' % (secret_key, salt)

def wp_hash(data, scheme='auth'):
    '''
    # 根据指定的 scheme，获取相应的salt，进行hmac运算
    @param data:
    @type data:
    @param scheme:
    @type scheme:
    '''

    salt = wp_salt(scheme)
    return hmac.new(salt, data).hexdigest()

def split_wp_cookie(cookie_str):
        try:
            uname, expire, mac = cookie_str.split('%7C')
        except:
            uname, expire, mac = '', '', ''

        return uname, expire, mac


def wp_validate_cookie(cookie, scheme):
    '''
    # 根据指定的scheme 效验cookie的合法性
    @param cookie:
    @type cookie:
    @param scheme:
    @type scheme:
    '''

    wp_uname, wp_expire, wp_mac = split_wp_cookie(cookie)

    wp_user_passwd = get_passwd_from_wpdb(wp_uname)

    # check cookie expire?
    if int(time.time()) > int(wp_expire):
        return False

    # check wordpress user db has that user
    if not wp_user_passwd:
        return False

    # check mac hash
    pass_frag = wp_user_passwd[8:8 + 4]
    wp_key = wp_hash('%s%s|%s' % (wp_uname, pass_frag, wp_expire), scheme)
    wp_mac_hash = hmac.new(wp_key, '%s|%s' % (wp_uname, wp_expire)).hexdigest()
    if wp_mac != wp_mac_hash:
        return False
    else:
        return True


class WpAuthBackend(object):

    if settings.WP_USER_SYNC:
        create_unknown_user = settings.WP_USER_SYNC
    else:
        create_unknown_user = True

    def authenticate(self, wp_cookies_dict):
        '''
        # 认证用户
        @param wp_cookies_dict:
        @type wp_cookies_dict:
        '''

        if not wp_cookies_dict:
            return
        user = None # set default user is None,
        username = self.clean_username(wp_cookies_dict)

        auth = wp_validate_cookie(wp_cookies_dict['wp_auth_cookie'], 'auth')
        logged_in = wp_validate_cookie(wp_cookies_dict['wp_logged_in_cookie'], 'logged_in')

        if auth and logged_in:

            if self.create_unknown_user:
                user, created = User.objects.get_or_create(username=username)
                if created:
                    user = self.configure_user(user)
            else:
                try:
                    user = User.objects.get(username=username)
                except User.DoesNotExist:
                    pass

        return user

    def clean_username(self, wp_cookies_dict):
        '''
        # return username ， do not trust cookie
        @param username:
        @type username:
        '''
        wp_auth_uname, wp_auth_expire, wp_auth_mac = split_wp_cookie(wp_cookies_dict['wp_auth_cookie'])
        wp_logged_in_uname, wp_logged_in_expire, wp_logged_in_mac = split_wp_cookie(wp_cookies_dict['wp_logged_in_cookie'])

        if wp_auth_uname == wp_logged_in_uname and wp_auth_expire == wp_logged_in_expire:
            return wp_logged_in_uname
        else:
            return ''

    def get_user(self, username):
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            return
        return user

    def configure_user(self, user):
        return user
